/**
 * order of including header files is very important:
 * first #include "../inference/bchaining.hpp" 
 * below #include "kbase.hpp"
 */
#include "kbase.hpp"
#include "utils.hpp"

#include "facts_searcher.hpp"
#include "fact_with_mask_searcher.hpp"

namespace mashine { namespace kb {

KnowledgeBase::KnowledgeBase()
{		
	APP_LOGGER(info) << "KnowledgeBase instantiated";
}

KnowledgeBase::~KnowledgeBase()
{
	delete strategy;
	
	APP_LOGGER(info) << "KnowledgeBase is distracted";
}

/**
 * return current inference strategy
 */
mashine::inference::InferenceStrategy * KnowledgeBase::getInferenceStrategy() const
{
	return strategy;
}

/**
 * set new inference strategy
 *
 * param strategy - pointer to new inference strategy
 */
void KnowledgeBase::setInferenceStrategy(mashine::inference::InferenceStrategy * strategy)
{
	this->strategy = strategy;
}

/**
 * realization delegate to inference strategy method
 *
 * param goal - goal of search
 *
 * return vector results of search of empty vector 
 */
std::vector<Literal> KnowledgeBase::inference(std::vector<Literal> const & goals) const
{
	std::vector<Literal> result = strategy->inference(goals);
	
	return result;			// =)  Oooo great C++
}

/**
 * if request valide return 0 
 * if invalid return first invalid request
 * ref msg - result message
 */
int KnowledgeBase::validateReques(std::vector<Literal> & target, std::string & msg)
{
	search::FactsSearchVisitor nameSearcher("*");

	int i = 0;
	BOOST_FOREACH(Literal & l, target)
	{
		std::vector<Literal> result = this->advanceSearch<Literal>(nameSearcher.setCriteria(l.getName()));
		
		BOOST_FOREACH(Literal & r, result)
		{
			if (r.getParams().size() != l.getParams().size())
			{
				msg = "different Literal params count in input and contains in base Literals";
				return i;
			}
		}
		
		++i;
	}
	
	return 0;
}

/**
 * this method call to add new rule
 * if rule alredy exist it ignored.
 * 
 * rule - add-on rule
 */
bool KnowledgeBase::add(Rule rule)
{
	// TODO add validation
	rules.push_back(rule);
}

/**
 * this method call to add new fact
 * if fact alredy exist it ignored.
 * 
 * fact - add-on fact
 */
bool KnowledgeBase::add(Literal fact)
{
	// TODO add validation
	facts.push_back(fact);
}

/**
 * this method call to add new analogy
 * if analogy alredy exist it ignored.
 * 
 * analogy - add-on analogy
 */
bool KnowledgeBase::add(Analogy analogy)
{
	// TODO add validation
	analogies.push_back(analogy);
}

/**
 * return pointer to vector of pointers to rules
 */
std::vector<Rule> const & KnowledgeBase::getRules() const
{
	return rules;
}

/**
 * return pointer to vector of pointers to facts
 */
std::vector<Literal> const & KnowledgeBase::getFacts() const
{
	return facts;
}

/**
 * return pointer to vector of pointers to analogies
 */
std::vector<Analogy> const & KnowledgeBase::getAnalogies() const
{
	return analogies;
}

}}